home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 090 / cpp.arc / CPP1.C < prev    next >
Text File  |  1985-12-03  |  36KB  |  936 lines

  1.  
  2. /*
  3.  * CPP main program.
  4.  *
  5.  * Edit history
  6.  * 21-May-84    MM      "Field test" release
  7.  * 23-May-84    MM      Some minor hacks.
  8.  * 30-May-84    ARF     Didn't get enough memory for __DATE__
  9.  *                      Added code to read stdin if no input
  10.  *                      files are provided.
  11.  * 29-Jun-84    MM      Added ARF's suggestions, Unixifying cpp.
  12.  * 11-Jul-84    MM      "Official" first release (that's what I thought!)
  13.  * 22-Jul-84    MM/ARF/SCK Fixed line number bugs, added cpp recognition
  14.  *                      of #line, fixed problems with #include.
  15.  * 23-Jul-84    MM      More (minor) include hacking, some documentation.
  16.  *                      Also, redid cpp's #include files
  17.  * 25-Jul-84    MM      #line filename isn't used for #include searchlist
  18.  *                      #line format is <number> <optional name>
  19.  * 25-Jul-84    ARF/MM  Various bugs, mostly serious.  Removed homemade doprint
  20.  * 01-Aug-84    MM      Fixed recursion bug, remove extra newlines and
  21.  *                      leading whitespace from cpp output.
  22.  * 02-Aug-84    MM      Hacked (i.e. optimized) out blank lines and unneeded
  23.  *                      whitespace in general.  Cleaned up unget()'s.
  24.  * 03-Aug-84    Keie    Several bug fixes from Ed Keizer, Vrije Universitet.
  25.  *                      -- corrected arg. count in -D and pre-defined
  26.  *                      macros.  Also, allow \n inside macro actual parameter
  27.  *                      lists.
  28.  * 06-Aug-84    MM      If debugging, dump the preset vector at startup.
  29.  * 12-Aug-84    MM/SCK  Some small changes from Sam Kendall
  30.  * 15-Aug-84    Keie/MM cerror, cwarn, etc. take a single string arg.
  31.  *                      cierror, etc. take a single int. arg.
  32.  *                      changed LINE_PREFIX slightly so it can be
  33.  *                      changed in the makefile.
  34.  * 31-Aug-84    MM      USENET net.sources release.
  35.  *  7-Sep-84    SCH/ado Lint complaints
  36.  * 10-Sep-84    Keie    Char's can't be signed in some implementations
  37.  * 11-Sep-84    ado     Added -C flag, pathological line number fix
  38.  * 13-Sep-84    ado     Added -E flag (does nothing) and "-" file for stdin.
  39.  * 14-Sep-84    MM      Allow # 123 as a synonym for #line 123
  40.  * 19-Sep-84    MM      scanid always reads to token, make sure #line is
  41.  *                      written to a new line, even if -C switch given.
  42.  *                      Also, cpp - - reads stdin, writes stdout.
  43.  * 03-Oct-84    ado/MM  Several changes to line counting and keepcomments
  44.  *                      stuff.  Also a rewritten control() hasher -- much
  45.  *                      simpler and no less "perfect". Note also changes
  46.  *                      in cpp3.c to fix numeric scanning.
  47.  * 04-Oct-84    MM      Added recognition of macro formal parameters if
  48.  *                      they are the only thing in a string, per the
  49.  *                      draft standard.
  50.  * 08-Oct-84    MM      One more attack on scannumber
  51.  * 15-Oct-84    MM/ado  Added -N to disable predefined symbols.  Fixed
  52.  *                      linecount if COMMENT_INVISIBLE enabled.
  53.  * 22-Oct-84    MM      Don't evaluate the #if/#ifdef argument if
  54.  *                      compilation is supressed.  This prevents
  55.  *                      unnecessary error messages in sequences such as
  56.  *                          #ifdef FOO          -- undefined
  57.  *                          #if FOO == 10       -- shouldn't print warning
  58.  * 25-Oct-84    MM      Fixed bug in false ifdef supression.  On vms,
  59.  *                      #include <foo> should open foo.h -- this duplicates
  60.  *                      the behavior of Vax-C
  61.  * 31-Oct-84    ado/MM  Parametized $ in indentifiers.  Added a better
  62.  *                      token concatenator and took out the trial
  63.  *                      concatenation code.  Also improved #ifdef code
  64.  *                      and cleaned up the macro recursion tester.
  65.  *  2-Nov-84    MM/ado  Some bug fixes in token concatenation, also
  66.  *                      a variety of minor (uninteresting) hacks.
  67.  *  6-Nov-84    MM      Happy Birthday.  Broke into 4 files and added
  68.  *                      #if sizeof (basic_types)
  69.  *  9-Nov-84    MM      Added -S* for pointer type sizes
  70.  * 13-Nov-84    MM      Split cpp1.c, added vms defaulting
  71.  * 23-Nov-84    MM/ado  -E supresses error exit, added CPP_INCLUDE,
  72.  *                      fixed strncpy bug.
  73.  *  3-Dec-84    ado/MM  Added OLD_PREPROCESSOR
  74.  *  7-Dec-84    MM      Stuff in Nov 12 Draft Standard
  75.  * 17-Dec-84    george  Fixed problems with recursive macros
  76.  * 17-Dec-84    MM      Yet another attack on #if's (f/t)level removed.
  77.  * 07-Jan-85    ado     Init defines before doing command line options
  78.  *                      so -Uunix works.
  79.  * 14-Jan-85    MM      Fixed bug with logical device translation on VMS.
  80.  * 18-Jan-85    MM      Rearrainged fgetname() conditionals.
  81.  * 27-Mar-85    ado     Fix bug in pcc
  82.  * 28-Mar-85    MM      Another attack on concatenation and some minor
  83.  *                      cleanup and typo corrections.
  84.  * 29-Mar-85    ado/MM  trigraphs, also fixed bug with / at end of macro.
  85.  * 11-Apr-85    ado     Buglets (typos and lint picking)
  86.  * 29-Apr-85    MM      Added concat without reexpansion.  Suggestion from ado.
  87.  * 07-Jun-85    KR      added -P option.  don't output #line
  88.  */
  89.  
  90. /*)BUILD
  91.         $(PROGRAM)      = cpp
  92.         $(FILES)        = { cpp1 cpp2 cpp3 cpp4 cpp5 cpp6 }
  93.         $(INCLUDE)      = { cppdef.h cpp.h }
  94.         $(STACK)        = 3000
  95.         $(TKBOPTIONS)   = {
  96.                 STACK   = 2000
  97.         }
  98. */
  99.  
  100. #ifdef  DOCUMENTATION
  101.  
  102. title   cpp             C Pre-Processor
  103. index                   C pre-processor
  104.  
  105. synopsis
  106.         .s.nf
  107.         cpp [-options] [infile [outfile]]
  108.         .s.f
  109. description
  110.  
  111.         CPP reads a C source file, expands macros and include
  112.         files, and writes an input file for the C compiler.
  113.         If no file arguments are given, CPP reads from stdin
  114.         and writes to stdout.  If one file argument is given,
  115.         it will define the input file, while two file arguments
  116.         define both input and output files.  The file name "-"
  117.         is a synonym for stdin or stdout as appropriate.
  118.  
  119.         The following options are supported.  Options may
  120.         be given in either case.
  121.         .lm +16
  122.         .p -16
  123.         -C              If set, source-file comments are written
  124.         to the output file.  This allows the output of CPP to be
  125.         used as the input to a program, such as lint, that expects
  126.         commands embedded in specially-formatted comments.
  127.         .p -16
  128.         -Dname=value    Define the name as if the programmer wrote
  129.  
  130.             #define name value
  131.  
  132.         at the start of the first file.  If "=value" is not
  133.         given, a value of "1" will be used.
  134.  
  135.         On non-unix systems, all alphabetic text will be forced
  136.         to upper-case.
  137.         .p -16
  138.         -E              Always return "success" to the operating
  139.         system, even if errors were detected.  Note that some fatal
  140.         errors, such as a missing #include file, will terminate
  141.         CPP, returning "failure" even if the -E option is given.
  142.         .p -16
  143.         -Idirectory     Add this directory to the list of
  144.         directories searched for #include "..." and #include <...>
  145.         commands.  Note that there is no space between the
  146.         "-I" and the directory string.  More than one -I command
  147.         is permitted.  On non-Unix systems "directory" is forced
  148.         to upper-case.
  149.         .p -16
  150.         -N              CPP normally predefines some symbols defining
  151.         the target computer and operating system.  If -N is specified,
  152.         no symbols will be predefined.  If -N -N is specified, the
  153.         "always present" symbols, __LINE__, __FILE__, and __DATE__
  154.         are not defined.
  155.         .p -16
  156.         -P              CPP normally writes lines of the form
  157.         #line <number> <file.name> to the output file so the compiler
  158.         can print the line number and name of the original source file
  159.         for diagnostic messages.  The -P option will suppress this output.
  160.         .p -16
  161.         -Stext          CPP normally assumes that the size of
  162.         the target computer's basic variable types is the same as the size
  163.         of these types of the host computer.  (This can be overridden
  164.         when CPP is compiled, however.)  The -S option allows dynamic
  165.         respecification of these values.  "text" is a string of
  166.         numbers, separated by commas, that specifies correct sizes.
  167.         The sizes must be specified in the exact order:
  168.  
  169.             char short int long float double
  170.  
  171.         If you specify the option as "-S*text", pointers to these
  172.         types will be specified.  -S* takes one additional argument
  173.         for pointer to function (e.g. int (*)())
  174.  
  175.         For example, to specify sizes appropriate for a PDP-11,
  176.         you would write:
  177.  
  178.                c s i l f d func
  179.              -S1,2,2,2,4,8,
  180.             -S*2,2,2,2,2,2,2
  181.  
  182.         Note that all values must be specified.
  183.         .p -16
  184.         -Tnumber        Enable (number = 1) or disable
  185.         trigraph recognition.  (If no number is given, the
  186.         default state is reversed.)  If enabled, the sequence
  187.         "??" is a character-escape to allow certain characters
  188.         to be entered on systems where the normal representation
  189.         is used for national letters.  This implementation
  190.         "merely" converts the trigraph to the internal representation,
  191.         and thus is probably incorrect.  A correct implementation
  192.         would seem to require recognition of Ansi escape sequences
  193.         in the input stream.  Someone else can write that routine.
  194.         .p -16
  195.         -Uname          Undefine the name as if
  196.  
  197.             #undef name
  198.  
  199.         were given.  On non-Unix systems, "name" will be forced to
  200.         upper-case.
  201.         .p -16
  202.         -Xnumber        Enable debugging code.  If no value is
  203.         given, a value of 1 will be used.  (For maintenence of
  204.         CPP only.)
  205.         .s.lm -16
  206.  
  207. Pre-Defined Variables
  208.  
  209.         When CPP begins processing, the following variables will
  210.         have been defined (unless the -N option is specified):
  211.         .s
  212.         Target computer (as appropriate):
  213.         .s
  214.             pdp11, vax, M68000 m68000 m68k
  215.         .s
  216.         Target operating system (as appropriate):
  217.         .s
  218.             rsx, rt11, vms, unix
  219.         .s
  220.         Target compiler (as appropriate):
  221.         .s
  222.             decus, vax11c
  223.         .s
  224.         The implementor may add definitions to this list.
  225.         The default definitions match the definition of the
  226.         host computer, operating system, and C compiler.
  227.         .s
  228.         The following are always available unless undefined (or
  229.         -N was specified twice):
  230.         .lm +16
  231.         .p -12
  232.         __FILE__        The input (or #include) file being compiled
  233.         (as a quoted string).
  234.         .p -12
  235.         __LINE__        The line number being compiled.
  236.         .p -12
  237.         __DATE__        The date and time of compilation as
  238.         a Unix ctime quoted string (the trailing newline is removed).
  239.         Thus,
  240.         .s
  241.             printf("Bug at line %s,", __LINE__);
  242.             printf(" source file %s", __FILE__);
  243.             printf(" compiled on %s", __DATE__);
  244.         .s.lm -16
  245.  
  246. Draft Proposed Ansi Standard Considerations
  247.  
  248.         The current version of the Draft Proposed Standard
  249.         explicitly states that "readers are requested not to specify
  250.         or claim conformance to this draft."  Readers and users
  251.         of Decus CPP should not assume that Decus CPP conforms
  252.         to the standard, or that it will conform to the actual
  253.         C Language Standard.
  254.  
  255.         When CPP is itself compiled, many features of the Draft
  256.         Proposed Standard that are incompatible with existing
  257.         preprocessors may be disabled.  See the comments in CPP's
  258.         source for details.
  259.  
  260.         The latest version of the Draft Proposed Standard (as reflected
  261.         in Decus CPP) is dated November 12, 1984.  A few things from
  262.         later drafts are included.
  263.  
  264.         Comments are removed from the input text.  The comment
  265.         is replaced by a single space character.  The -C option
  266.         preserves comments, writing them to the output file.
  267.  
  268.         The '$' character is considered to be a letter.  This is
  269.         a permitted extension.
  270.  
  271.         The following new features of C are processed by CPP:
  272.         .s.comment Note: significant spaces, not tabs, .br quotes #if, #elif
  273.         .br;####_#elif expression    (_#else _#if)
  274.         .br;####'_\xNNN'             (Hexadecimal constant)
  275.         .br;####'_\a'                (Ascii BELL)
  276.         .br;####'_\v'                (Ascii Vertical Tab)
  277.         .br;####_#if defined NAME    1 if defined, 0 if not
  278.         .br;####_#if defined (NAME)  1 if defined, 0 if not
  279.         .br;####_#if sizeof (basic type)
  280.         .br;####unary +
  281.         .br;####123U, 123LU         Unsigned ints and longs.
  282.         .br;####12.3L               Long double numbers
  283.         .br;####_#token              Stringize token
  284.         .br;####token_#_#token        Token concatenation
  285.         .br;####_#include token      Expands to filename
  286.  
  287.         The proposed national replacement letter fallbacks, using
  288.         "??", have not been implemented.
  289.  
  290.         The Draft Proposed Standard has extended C, adding a constant
  291.         string concatenation operator, where
  292.  
  293.             "foo" "bar"
  294.  
  295.         is regarded as the single string "foobar".  (This does not
  296.         affect CPP's processing but does permit a limited form of
  297.         macro argument substitution into strings as will be discussed.)
  298.  
  299.         The Standard Committee plans to add token concatenation
  300.         to #define command lines.  One suggested implementation
  301.         is as follows:  the sequence "Token1##Token2" is treated
  302.         as if the programmer wrote "Token1Token2".  This could
  303.         be used as follows:
  304.  
  305.             #line 123
  306.             #define ATLINE foo##__LINE__
  307.  
  308.         ATLINE would be defined as foo123.
  309.  
  310.         Note that "Token2" must either have the format of an
  311.         identifier or be a string of digits.  Thus, the string
  312.  
  313.             #define ATLINE foo##1x3
  314.  
  315.         generates two tokens: "foo1" and "x3".
  316.  
  317.         If the tokens T1 and T2 are concatenated into T3,
  318.         this implementation operates as follows:
  319.  
  320.           1. Expand T1 if it is a macro.
  321.           2. Expand T2 if it is a macro.
  322.           3. Join the tokens, forming T3.
  323.           4. Output T3 (without reexpansion).
  324.  
  325.         As implemented here, ## left-associates.  I.e., a##b##c
  326.         is effectively (a##b)##c.  Cpp can be compiled so as
  327.         to re-expand the constructed macro.
  328.  
  329.         A macro formal parameter will be substituted into a string
  330.         or character constant if it is preceded by a single #.
  331.  
  332.             #define VECSIZE 123
  333.             #define vprint(name, size) \
  334.               printf("name" "[" #size "] = {\n")
  335.               ... vprint(vector, VECSIZE);
  336.  
  337.         expands (effectively) to
  338.  
  339.               vprint("vector[123] = {\n");
  340.  
  341.         Note that this will be useful if your C compiler supports
  342.         the new string concatenation operation noted above.
  343.  
  344. error messages
  345.  
  346.         Many.  CPP prints warning or error messages if you try to
  347.         use multiple-byte character constants (non-transportable)
  348.         if you #undef a symbol that was not defined, or if your
  349.         program has potentially nested comments.
  350.  
  351. author
  352.  
  353.         Martin Minow
  354.  
  355. bugs
  356.  
  357.         The #if expression processor uses signed integers only.
  358.         I.e, #if 0xFFFFu < 0 may be TRUE.
  359.  
  360.         A / at the end of a macro expansion will not introduce
  361.         a comment:
  362.  
  363.             #define foo /
  364.                 foo* this is not a comment */
  365.  
  366. #endif
  367.  
  368.  
  369.  
  370.  
  371.  
  372.  
  373.  
  374.  
  375.  
  376.  
  377.  
  378.  
  379. #include        <stdio.h>
  380. #include        <ctype.h>
  381. #include        "cppdef.h"
  382. #include        "cpp.h"
  383.  
  384. /*
  385.  * Commonly used global variables:
  386.  * line         is the current input line number.
  387.  * wrongline    is set in many places when the actual output
  388.  *              line is out of sync with the numbering, e.g,
  389.  *              when expanding a macro with an embedded newline.
  390.  *
  391.  * token        holds the last identifier scanned (which might
  392.  *              be a candidate for macro expansion).
  393.  * errors       is the running cpp error counter.
  394.  * infile       is the head of a linked list of input files (extended by
  395.  *              #include and macros being expanded).  infile always points
  396.  *              to the current file/macro.  infile->parent to the includer,
  397.  *              etc.  infile->fd is NULL if this input stream is a macro.
  398.  */
  399. int             line;                   /* Current line number          */
  400. int             wrongline;              /* Force #line to compiler      */
  401. char            token[IDMAX + 1];       /* Current input token          */
  402. int             errors;                 /* cpp error counter            */
  403. FILEINFO        *infile = NULL;         /* Current input file           */
  404. #if DEBUG
  405. int             debug;                  /* TRUE if debugging now        */
  406. #endif
  407. /*
  408.  * This counter is incremented when a macro expansion is initiated.
  409.  * If it exceeds a built-in value, the expansion stops -- this tests
  410.  * for a runaway condition:
  411.  *      #define X Y
  412.  *      #define Y X
  413.  *      X
  414.  * This can be disabled by falsifying rec_recover.  (Nothing does this
  415.  * currently: it is a hook for an eventual invocation flag.)
  416.  */
  417. int             recursion;              /* Infinite recursion counter   */
  418. int             rec_recover = TRUE;     /* Unwind recursive macros      */
  419.  
  420. /*
  421.  * instring is set TRUE when a string is scanned.  It modifies the
  422.  * behavior of the "get next character" routine, causing all characters
  423.  * to be passed to the caller (except <DEF_MAGIC>).  Note especially that
  424.  * comments and \<newline> are not removed from the source.  (This
  425.  * prevents cpp output lines from being arbitrarily long).
  426.  *
  427.  * inmacro is set by #define -- it absorbs comments and converts
  428.  * form-feed and vertical-tab to space, but returns \<newline>
  429.  * to the caller.  Strictly speaking, this is a bug as \<newline>
  430.  * shouldn't delimit tokens, but we'll worry about that some other
  431.  * time -- it is more important to prevent infinitly long output lines.
  432.  *
  433.  * instring and inmacro are parameters to the get() routine which
  434.  * were made global for speed.
  435.  */
  436. int             instring = FALSE;       /* TRUE if scanning string      */
  437. int             inmacro = FALSE;        /* TRUE if #defining a macro    */
  438.  
  439. /*
  440.  * work[] and workp are used to store one piece of text in a temporary
  441.  * buffer.  To initialize storage, set workp = work.  To store one
  442.  * character, call save(c);  (This will fatally exit if there isn't
  443.  * room.)  To terminate the string, call save(EOS).  Note that
  444.  * the work buffer is used by several subroutines -- be sure your
  445.  * data won't be overwritten.  The extra byte in the allocation is
  446.  * needed for string formal replacement.
  447.  */
  448. char            work[NWORK + 1];        /* Work buffer                  */
  449. char            *workp;                 /* Work buffer pointer          */
  450.  
  451. /*
  452.  * keepcomments is set TRUE by the -C option.  If TRUE, comments
  453.  * are written directly to the output stream.  This is needed if
  454.  * the output from cpp is to be passed to lint (which uses commands
  455.  * embedded in comments).  cflag contains the permanent state of the
  456.  * -C flag.  keepcomments is always falsified when processing #control
  457.  * commands and when compilation is supressed by a false #if
  458.  *
  459.  * If eflag is set, CPP returns "success" even if non-fatal errors
  460.  * were detected.
  461.  *
  462.  * If nflag is non-zero, no symbols are predefined except __LINE__.
  463.  * __FILE__, and __DATE__.  If nflag > 1, absolutely no symbols
  464.  * are predefined.
  465.  */
  466. int             keepcomments = FALSE;   /* Write out comments flag      */
  467. int             cflag = FALSE;          /* -C option (keep comments)    */
  468. int             eflag = FALSE;          /* -E option (never fail)       */
  469. int             nflag = 0;              /* -N option (no predefines)    */
  470. int             pflag = FALSE;          /* -P option (no #line output)  */
  471. int             tflag = TFLAG_INIT;     /* -T option (trigraphs)        */
  472.  
  473. /*
  474.  * ifstack[] holds information about nested #if's.  It is always
  475.  * accessed via *ifptr.  The information is as follows:
  476.  *      WAS_COMPILING   state of compiling flag at outer level.
  477.  *      ELSE_SEEN       set TRUE when #else seen to prevent 2nd #else.
  478.  *      TRUE_SEEN       set TRUE when #if or #elif succeeds
  479.  * ifstack[0] holds the compiling flag.  It is WAS_COMPILING if
  480.  * compilation is currently enabled.  Note that this must be
  481.  * initialized to WAS_COMPILING.
  482.  */
  483. char            ifstack[BLK_NEST] = { WAS_COMPILING };
  484. char            *ifptr = ifstack;               /* -> current ifstack[] */
  485.  
  486. /*
  487.  * incdir[] stores the -i directories (and the system-specific
  488.  * #include <...> directories.
  489.  */
  490. char    *incdir[NINCLUDE];              /* -i directories               */
  491. char    **incend = incdir;              /* -> free space in incdir[]    */
  492.  
  493. /*
  494.  * This is the table used to predefine target machine and operating
  495.  * system designators.  It may need hacking for specific circumstances.
  496.  * Note: it is not clear that this is part of the Ansi Standard.
  497.  * The -N option supresses preset definitions.
  498.  */
  499. char    *preset[] = {                   /* names defined at cpp start   */
  500. #ifdef  MACHINE
  501.         MACHINE,
  502. #endif
  503. #ifdef  SYSTEM
  504.         SYSTEM,
  505. #endif
  506. #ifdef  COMPILER
  507.         COMPILER,
  508. #endif
  509. #if     DEBUG
  510.         "decus_cpp",                    /* Ourselves!                   */
  511. #endif
  512.         NULL                            /* Must be last                 */
  513. };
  514.  
  515. /*
  516.  * The value of these predefined symbols must be recomputed whenever
  517.  * they are evaluated.  The order must not be changed.
  518.  */
  519. char    *magic[] = {                    /* Note: order is important     */
  520.         "__LINE__",
  521.         "__FILE__",
  522.         NULL                            /* Must be last                 */
  523. };
  524.  
  525. /*
  526.  * This variable is used to determine the memory model for MS-DOS.
  527.  * See cppdef.h for more information.
  528.  */
  529.  
  530. #if    HOST == SYS_MSDOS
  531. #ifdef    M_I86SM
  532. char ms_dos_model = 's';
  533. #else
  534. #ifdef    M_I86MM
  535. char ms_dos_model = 'm';
  536. #else
  537. #ifdef    M_I86LM
  538. char ms_dos_model = 'l';
  539. #else
  540. #ifdef    I8086S
  541. char ms_dos_model = 's';
  542. #else
  543. #ifdef    I8086P
  544. char ms_dos_model = 'p';
  545. #else
  546. #ifdef    I8086D
  547. char ms_dos_model = 'd';
  548. #else
  549. #ifdef    I8086L
  550. char ms_dos_model = 'l';
  551. #endif
  552. #endif
  553. #endif
  554. #endif
  555. #endif
  556. #endif
  557. #endif
  558. #endif
  559.  
  560.  
  561.  
  562.  
  563.  
  564.  
  565.  
  566.  
  567.  
  568.  
  569.  
  570.  
  571.  
  572.  
  573.  
  574.  
  575.  
  576.  
  577.  
  578.  
  579.  
  580.  
  581.  
  582. main(argc, argv)
  583. int             argc;
  584. char            *argv[];
  585. {
  586.         register int    i;
  587.  
  588. #if HOST == SYS_VMS
  589.         argc = getredirection(argc, argv);      /* vms >file and <file  */
  590. #endif
  591.         initdefines();                          /* O.S. specific def's  */
  592.         i = dooptions(argc, argv);              /* Command line -flags  */
  593.  
  594. #if    HOST == SYS_MSDOS
  595.             /*    Undefine inappropriate memory-model
  596.              * predefines, based on either the default memory
  597.              * model (see ms_dos_model) or the user-supplied
  598.              * memory model provided by the '-M' switch in
  599.              * dooptions() (in cpp3.c).
  600.              */
  601.     switch( ms_dos_model )
  602.     {
  603.         case 's' :    /* Small Model, Small data, small pointers...    */
  604.         case 'p' :    /* Large Code, Small Data, small pointers...    */
  605.                 /* Delete invalid MSC predefinitions...    */
  606.         defendel( "M_I86MM", TRUE );
  607.         defendel( "M_I86LM", TRUE );
  608.                 /* And invalid Lattice predefinitions    */
  609.         defendel( "LPTR", TRUE );
  610.         defendel( "I8086D", TRUE );
  611.         defendel( "I8086L", TRUE );
  612.         if ( ms_dos_model == 's' )
  613.             defendel( "I8086P", TRUE );
  614.         else {
  615.             defendel( "I8086S", TRUE );
  616.             defendel( "M_I86SM", TRUE );
  617.         } /* End if */
  618.         break;
  619.  
  620.         case 'd' :    /* Small Code, Large Data, large pointers...    */
  621.         case 'l' :    /* Large Code, Large Data, large pointers...    */
  622.                 /* Delete invalid MSC predefinitions    */
  623.         defendel( "M_I86MM", TRUE );
  624.         defendel( "M_I86SM", TRUE );
  625.                 /* And invalid Lattice predefinitions    */
  626.         defendel( "SPTR", TRUE );
  627.         defendel( "I8086S", TRUE );
  628.         defendel( "I8086P", TRUE );
  629.         if ( ms_dos_model == 'd' )
  630.         {
  631.             defendel( "I8086L", TRUE );
  632.             defendel( "M_I86LM", TRUE );
  633.         } else
  634.             defendel( "I8086D", TRUE );
  635.         break;
  636.  
  637.         case 'm' :    /* Large code, small data, mixed pointers...    */
  638.                 /* Delete invalid MSC predefinitions    */
  639.         defendel( "M_I86SM", TRUE );
  640.         defendel( "M_I86LM", TRUE );
  641.                 /* And invalid Lattice predefinitions    */
  642.         defendel( "LPTR", TRUE );
  643.         defendel( "SPTR", TRUE );
  644.         defendel( "I8086D", TRUE );
  645.         defendel( "I8086L", TRUE );
  646.         defendel( "I8086P", TRUE );
  647.         defendel( "I8086S", TRUE );
  648.         break;
  649.     } /* End switch */
  650. #endif
  651.  
  652.         switch (i) {
  653.         case 3:
  654.             /*
  655.              * Get output file, "-" means use stdout.
  656.              */
  657.             if (!streq(argv[2], "-")) {
  658. #if HOST == SYS_VMS
  659.                 /*
  660.                  * On vms, reopen stdout with "vanilla rms" attributes.
  661.                  */
  662.                 if ((i = creat(argv[2], 0, "rat=cr", "rfm=var")) == -1
  663.                  || dup2(i, fileno(stdout)) == -1) {
  664. #else
  665.                 if (freopen(argv[2], "w", stdout) == NULL) {
  666. #endif
  667.                     perror(argv[2]);
  668.                     cerror("Can't open output file \"%s\"", argv[2]);
  669.                     exit(IO_ERROR);
  670.                 }
  671.             }                           /* Continue by opening input    */
  672.         case 2:                         /* One file -> stdin            */
  673.             /*
  674.              * Open input file, "-" means use stdin.
  675.              */
  676.             if (!streq(argv[1], "-")) {
  677.                 if (freopen(argv[1], "r", stdin) == NULL) {
  678.                     perror(argv[1]);
  679.                     cerror("Can't open input file \"%s\"", argv[1]);
  680.                     exit(IO_ERROR);
  681.                 }
  682.                 strcpy(work, argv[1]);  /* Remember input filename      */
  683.                 break;
  684.             }                           /* Else, just get stdin         */
  685.         case 0:                         /* No args?                     */
  686.         case 1:                         /* No files, stdin -> stdout    */
  687. #if HOST == SYS_VMS || HOST == SYS_RSX || HOST == SYS_RT11
  688.             fgetname(stdin, work);      /* Vax-11C, Decus C know name   */
  689. #else
  690.             work[0] = EOS;              /* Unix can't find stdin name   */
  691. #endif
  692.             break;
  693.  
  694.         default:
  695.             exit(IO_ERROR);             /* Can't happen                 */
  696.         }
  697.         setincdirs();                   /* Setup -I include directories */
  698.         addfile(stdin, work);           /* "open" main input file       */
  699. #if DEBUG
  700.         if (debug > 0)
  701.             dumpdef("preset #define symbols");
  702. #endif
  703.         cppmain();                      /* Process main file            */
  704.         if ((i = (ifptr - &ifstack[0])) != 0) {
  705. #if OLD_PREPROCESSOR
  706.             ciwarn("Inside #ifdef block at end of input, depth = %d", i);
  707. #else
  708.             cierror("Inside #ifdef block at end of input, depth = %d", i);
  709. #endif
  710.         }
  711.         fclose(stdout);
  712.         if (errors > 0) {
  713.             fprintf(stderr, (errors == 1)
  714.                 ? "%d error in preprocessor\n"
  715.                 : "%d errors in preprocessor\n", errors);
  716.             if (!eflag)
  717.                 exit(IO_ERROR);
  718.         }
  719.         exit(IO_SUCCESS);               /* No errors or -E option set   */
  720. }
  721.  
  722.  
  723.  
  724.  
  725.  
  726.  
  727.  
  728.  
  729.  
  730.  
  731.  
  732.  
  733.  
  734.  
  735.  
  736.  
  737. FILE_LOCAL
  738. cppmain()
  739. /*
  740.  * Main process for cpp -- copies tokens from the current input
  741.  * stream (main file, include file, or a macro) to the output
  742.  * file.
  743.  */
  744. {
  745.         register int            c;              /* Current character    */
  746.         register int            counter;        /* newlines and spaces  */
  747.         extern int              output();       /* Output one character */
  748.  
  749.         /*
  750.          * Explicitly output a #line at the start of cpp output so
  751.          * that lint (etc.) knows the name of the original source
  752.          * file.  If we don't do this explicitly, we may get
  753.          * the name of the first #include file instead.
  754.          *
  755.          * The extra putchar() and sharp() works around a bug in pcc.
  756.          */
  757.         sharp();
  758.         putchar('\n');
  759.         sharp();
  760.         /*
  761.          * This loop is started "from the top" at the beginning of each line
  762.          * wrongline is set TRUE in many places if it is necessary to write
  763.          * a #line record.  (But we don't write them when expanding macros.)
  764.          *
  765.          * The counter variable has two different uses:  at
  766.          * the start of a line, it counts the number of blank lines that
  767.          * have been skipped over.  These are then either output via
  768.          * #line records or by outputting explicit blank lines.
  769.          * When expanding tokens within a line, the counter remembers
  770.          * whether a blank/tab has been output.  These are dropped
  771.          * at the end of the line, and replaced by a single blank
  772.          * within lines.
  773.          */
  774.         for (;;) {
  775.             counter = 0;                        /* Count empty lines    */
  776.             for (;;) {                          /* For each line, ...   */
  777.                 while (type[(c = get())] == SPA) /* Skip leading blanks */
  778.                     ;                           /* in this line.        */
  779.                 if (c == '\n')                  /* If line's all blank, */
  780.                     ++counter;                  /* Do nothing now       */
  781.                 else if (c == '#') {            /* Is 1st non-space '#' */
  782.                     keepcomments = FALSE;       /* Don't pass comments  */
  783.                     counter = control(counter); /* Yes, do a #command   */
  784.                     keepcomments = (cflag && compiling);
  785.                 }
  786.                 else if (c == EOF_CHAR)         /* At end of file?      */
  787.                     break;
  788.                 else if (!compiling) {          /* #ifdef false?        */
  789.                     skipnl();                   /* Skip to newline      */
  790.                     counter++;                  /* Count it, too.       */
  791.                 }
  792.                 else {
  793.                     break;                      /* Actual token         */
  794.                 }
  795.             }
  796.             if (c == EOF_CHAR)                  /* Exit process at      */
  797.                 break;                          /* End of file          */
  798.             /*
  799.              * If the loop didn't terminate because of end of file, we
  800.              * know there is a token to compile.  First, clean up after
  801.              * absorbing newlines.  counter has the number we skipped.
  802.              */
  803.             if ((wrongline && infile->fp != NULL) || counter > 4)
  804.                 sharp();                        /* Output # line number */
  805.             else {                              /* If just a few, stuff */
  806.                 while (--counter >= 0)          /* them out ourselves   */
  807.                     putchar('\n');
  808.             }
  809.             /*
  810.              * Process each token on this line.
  811.              */
  812.             unget();                            /* Reread the char.     */
  813.             for (;;) {                          /* For the whole line,  */
  814.                 for (counter = 0; (type[(c = get())] == SPA);) {
  815. #if COMMENT_INVISIBLE | OK_CONCAT == CON_NOEXPAND
  816.                     if (c != COM_SEP)
  817.                         counter++;
  818. #else
  819.                     counter++;                  /* Skip over blanks     */
  820. #endif
  821.                 }
  822.                 if (c == EOF_CHAR || c == '\n')
  823.                     goto end_line;              /* Exit line loop       */
  824.                 else if (counter > 0)           /* If we got any spaces */
  825.                     putchar(' ');               /* Output one space     */
  826.                 c = macroid(c);                 /* Grab the token       */
  827.                 if (c == EOF_CHAR || c == '\n') /* From macro exp error */
  828.                     goto end_line;              /* Exit line loop       */
  829.                 switch (type[c]) {
  830.                 case LET:
  831.                     if (!catenate())            /* Anything happen?     */
  832.                         fputs(token, stdout);   /* Quite ordinary token */
  833.                     break;
  834.  
  835.                 case DIG:                       /* Output a number      */
  836.                 case DOT:                       /* Dot may begin floats */
  837.                     scannumber(c, output);
  838.                     break;
  839.  
  840.                 case QUO:                       /* char or string const */
  841.                     scanstring(c, output);      /* Copy it to output    */
  842.                     break;
  843.  
  844.                 default:                        /* Some other character */
  845.                     if (c == TOK_SEP) {
  846.                         unget();                /* Catenate must see it */
  847.                         token[0] = EOS;         /* Nothing on left side */
  848.                         catenate();
  849.                     }
  850.                     else {
  851.                         cput(c);                /* Just output it       */
  852.                     }
  853.                     break;
  854.                 }                               /* Switch ends          */
  855.             }                                   /* Line for loop        */
  856. end_line:   if (c == '\n') {                    /* Compiling at EOL?    */
  857.                 putchar('\n');                  /* Output newline, if   */
  858.                 if (infile->fp == NULL)         /* Expanding a macro,   */
  859.                     wrongline = TRUE;           /* Output # line later  */
  860.             }
  861.         }                                       /* Continue until EOF   */
  862. }
  863.  
  864.  
  865.  
  866.  
  867.  
  868.  
  869.  
  870.  
  871.  
  872.  
  873.  
  874.  
  875.  
  876.  
  877.  
  878.  
  879.  
  880.  
  881. output(c)
  882. int             c;
  883. /*
  884.  * Output one character to stdout -- output() is passed as an
  885.  * argument to scanstring()
  886.  */
  887. {
  888.         switch (c) {
  889.         case ST_QUOTE:                          /* Stringizer magic     */
  890.             putchar('"');
  891.             break;
  892.  
  893.         case TOK_SEP:                           /* Token separator      */
  894. #if COMMENT_INVISIBLE | OK_CONCAT == CON_NOEXPAND
  895.         case COM_SEP:                           /* Comment magic        */
  896. #endif
  897.             break;                              /* These are ignored    */
  898.  
  899.         default:
  900.             putchar(c);
  901.         }
  902. }
  903.  
  904. static char     *sharpfilename = NULL;
  905.  
  906. FILE_LOCAL
  907. sharp()
  908. /*
  909.  * Output a line number line.
  910.  */
  911. {
  912.         register char           *name;
  913.  
  914.         if (keepcomments)                       /* Make sure # comes on */
  915.             putchar('\n');                      /* a fresh, new line.   */
  916.         if (pflag)
  917.             goto sharp_exit;
  918.         printf("#%s %d", LINE_PREFIX, line);
  919.         if (infile->fp != NULL) {
  920.             name = (infile->progname != NULL)
  921.                 ? infile->progname : infile->filename;
  922.             if (sharpfilename == NULL
  923.              || sharpfilename != NULL && !streq(name, sharpfilename)) {
  924.                 if (sharpfilename != NULL)
  925.                     free(sharpfilename);
  926.                 sharpfilename = savestring(name);
  927.                 printf(" \"%s\"", name);
  928.              }
  929.         }
  930.         putchar('\n');
  931.  
  932. sharp_exit:
  933.         wrongline = FALSE;
  934. }
  935.  
  936.